package com.geek.zookeeper.lock;

import com.geek.zookeeper.connect.Connect;
import com.geek.zookeeper.connect.impl.ConnectImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * 基于zookeeper实现的非公平锁
 */
@Slf4j
public class ZooUnfairLock implements Runnable {

	private ZooKeeper zoo;

	private static final String PATH = "/unfairLock";

	public ZooUnfairLock() throws IOException, InterruptedException {
		Connect connect = new ConnectImpl();
		this.zoo = connect.init();
	}

	/**
	 * 实现原理
	 * 创建节点，创建失败则对节点监听，之后再抢锁创建节点
	 */
	public void lock() throws Exception {
		byte[] bytes = ("lock-"+Thread.currentThread().getName()).getBytes(StandardCharsets.UTF_8);
		log.debug("开始获取锁");

		try {
			String result = zoo.create(PATH, bytes, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
			System.out.println("获取锁成功："+result);

		} catch (KeeperException e) {
			log.error(e.getMessage());
			log.info("节点已经创建，等待锁");
			Watcher watcher = new Watcher() {
				@SneakyThrows
				@Override
				public void process(WatchedEvent watchedEvent) {
					lock();
				}
			};
			zoo.getData(PATH, watcher, null);

		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}

	@SneakyThrows
	@Override
	public void run() {
		this.lock();
	}

	public static void main(String[] args) throws Exception {
		ZooUnfairLock lock = new ZooUnfairLock();

		Thread t1 = new Thread(lock, "t1");
		t1.start();

		Thread t2 = new Thread(lock, "t2");
		t2.start();


		TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
	}

}
